﻿#include "MoveObject.h"
#include "SweptAABB.h"
#include "ShareComponents.h"
#include "QuadTree.h"
#include "StaticObject.h"
#include "Box.h"
#include <math.h>


#define GAME_TIME 1000.0f / 60.0f;
#define CLIMB_TIME 30.0f;

MoveObject::MoveObject()
{			
	_direction = 1;
	_mBox = NULL;
	_moveState = ON_SPACE;
	_boundBox = new Box(D3DXVECTOR2(),D3DXVECTOR2(),D3DXVECTOR2());
	_currentGround = NULL;
	_fallFromGround = NULL;
	_groundingState = SPACE_NONE;
	_moveBox = new Box(D3DXVECTOR2(),D3DXVECTOR2(),D3DXVECTOR2());
	_direction = 1;
}

MoveObject::~MoveObject(void)
{

}

bool MoveObject::AssignMove(Box* parentBox)
{
	if(parentBox == NULL) return false;
	this->_mBox = parentBox;
	return true;
}

void MoveObject::moveSinY(int a)
{
	/////
	_mBox->_position.x += _mBox->_v.x;
	_mBox->_position.y +=  a * sin(_angle);
	_mBox->_v.y = a * sin(_angle);	
	this->_increaseAngle(); 
}

void MoveObject::_increaseAngle()
{
	this->_angle += 0.1f;
	if(this->_angle >= 2*3.14f)
		this->_angle = 0;
}

void MoveObject::moveFollowAngle(float time, float angle)
{
	_mBox->_position.x += cos(angle) * time * _mBox->_v.x;
	_mBox->_position.y += sin(angle ) * time * _mBox->_v.y;
}

void MoveObject::move()
{

	canFallDown();
	float _remainTime = 1.0f;
	float nx = 0.0f;
	float ny = 0.0f;
	//luu y cac _mBox se dc dc thay the == checkMoveBox
	Box* _checkMove = _getMoveBox();
	switch (_moveState)
	{
	case ON_GROUND:
		{
			_groundingState = SPACE_NONE;
			this->_mBox->_position.x += _mBox->_v.x;
			if(_mBox->_v.y > 0.0f) 
			{
				_moveState = ON_SPACE;
				return;
			}
			//co cac ground ke tiep
			
			//khong co cac ground ke tiep
			bool _chkLeft = _mBox->getLeft() + _checkMove->_size.x/2 < _currentGround->getBox()->getLeft();
			bool _chkRight = _mBox->getRight() - _checkMove->_size.x/2 > _currentGround->getBox()->getRight();
			if( _chkLeft||_chkRight)
			{			
				_remainTime = SweptAABB::sweptAABBCheck(_checkMove,_currentGround->getBox(),nx,ny);
				if(_remainTime == 1.0f)
				{
					_moveState = ON_SPACE;
					_mBox->_v.y = -g;					

				}
			}

		}
		break;
	case ON_WATER:
		{			
			_groundingState = SPACE_NONE;
			this->_mBox->_position.x += _mBox->_v.x;			
			//khong co ground ke tiep
			//bool _chkLeft = _mBox->getLeft() + _checkMove->_size.x/2 < _currentGround->getBox()->getLeft();
			//bool _chkRight = _mBox->getRight() - _checkMove->_size.x/2 > _currentGround->getBox()->getRight();
			bool _chkLeft = _mBox->getLeft()  < _currentGround->getBox()->getLeft();
			bool _chkRight = _mBox->getRight()  > _currentGround->getBox()->getRight();
			if( _chkLeft||_chkRight)
			{			
				_remainTime = SweptAABB::sweptAABBCheck(_mBox,_currentGround->getBox(),nx,ny);
				if(_remainTime == 1.0f)
				{									
					_mBox->_v.y = -g;					
					_moveState = ON_SPACE;
				}
			}
		}
		break;
	case ON_SPACE:
		{
			this->_mBox->_position.x += _mBox->_v.x;			
			list<StaticObject*> sGround = gl_Quadtree->query_staticObj(_getBoundBox());			
			for (StaticObject* i : sGround)
			{				
				//thay the mBox = checkBox
				_remainTime = SweptAABB::sweptAABBCheck(_checkMove,i->getBox(),nx,ny);				
				if(_remainTime < 1.0f && nx == 0.0f && ny == 1.0f)
				{
					_currentGround = i;
					_moveState = i->getID() == WATER ? ON_WATER : ON_GROUND;
					_fallDown(_remainTime);
					return;
				}
			}
			_fallDown(1.0f);
		}
		break;
	case FALL_DOWN:
		{
			//please, nhan gium phim s va u
			this->_mBox->_position.x += _mBox->_v.x;			
			list<StaticObject*> sGround = gl_Quadtree->query_staticObj(_getBoundBox());			
			for (StaticObject* i : sGround)
			{
				if(i == _fallFromGround) continue;
				//thay the mBox = checkBox
				_remainTime = SweptAABB::sweptAABBCheck(_checkMove,i->getBox(),nx,ny);				
				if(_remainTime < 1.0f && nx == 0.0f && ny == 1.0f)
				{
					_currentGround = i;
					_moveState = i->getID() == WATER ? ON_WATER : ON_GROUND;
					_fallDown(_remainTime);
					return;
				}
			}
			_fallDown(1.0f);
		}
		break;
		/*case CLIMB_LEFT:
		{		
		if(_mBox->getLeft() > _currentGround->getBox()->getLeft())
		{
		_climbDelay += GAME_TIME;
		bool chk = _climbDelay > CLIMB_TIME;
		if(chk)
		{
		_moveState = _currentGround->getID() == WATER ? ON_WATER : ON_GROUND;
		_climbDelay = 0;
		}					
		}
		else
		{
		_mBox->_position.x += 2.4f;
		}
		}
		break;
		case CLIMB_RIGHT:
		{		
		if(_mBox->getRight() < _currentGround->getBox()->getRight())
		{
		_climbDelay += GAME_TIME;
		bool chk = _climbDelay > CLIMB_TIME;
		if(chk)
		{
		_moveState = _currentGround->getID() == WATER ? ON_WATER : ON_GROUND;
		_climbDelay = 0;
		}								
		}
		else
		{
		_mBox->_position.x -= 2.4f;
		}
		}
		break;*/
	}
}

void MoveObject::_fallDown(float remainTime)
{
	_mBox->_position.y += _mBox->_v.y * remainTime;
	_mBox->_v.y += g;
}

Box* MoveObject::_getBoundBox()
{
	this->_boundBox->_size = _mBox->_size;
	_boundBox->_position = _mBox->_position;
	_boundBox->_v = _mBox->_v;
	_boundBox->_size.y += 50;
	_boundBox->_position.y -= 50;
	return _boundBox;
}

bool MoveObject::isOnSpace()
{
	return _moveState == ON_SPACE;
}

bool MoveObject::isOnWater()
{
	return _moveState == ON_WATER;
}

bool MoveObject::isOnGround()
{
	return _moveState == ON_GROUND;
}

MOVE_STATE MoveObject::isGrounding()
{
	float _remain = 1.0f;
	float nx,ny;
	list<StaticObject*> obj = gl_Quadtree->query_staticObj(_getBoundBox());
	Box* _move =  _getMoveBox();
	_boundBox->_size = _move->_size;
	_boundBox->_position = _move->_position;
	_boundBox->_v = _move->_v;
	_boundBox->_size.y = 15;
	_boundBox->_position.y -= 30;
	float rTime = 1.0f,x = 0, y = 0;
	gl_predict =new Box(_boundBox->_position,_boundBox->_size,_boundBox->_v);
	for (StaticObject* i : obj)
	{
		if(_moveState == FALL_DOWN) if(i == _fallFromGround) continue;
		_remain= SweptAABB::sweptAABBCheck(_boundBox,i->getBox(),nx,ny);
		rTime= SweptAABB::sweptAABBCheck(_move,i->getBox(),x,y);
		if((_remain < 1.0f && nx == 0.0f && ny == 1.0f) ||
			( rTime < 1.0f && x == 0.0f && y == 1.0f))
		{
			_groundingState = i->getID() == WATER ? SPACE_WATER : SPACE_GROUND;
			return _groundingState;
		}	


	}

	return _groundingState ;
}

bool MoveObject::canFallDown()
{
	_boundBox->_position = _mBox->_position;
	_boundBox->_size = _mBox->_size;
	_boundBox->_position.y = 0;
	_boundBox->_size.y = _mBox->getBottom();
	gl_fall = new Box(_boundBox->_position,_boundBox->_size,_boundBox->_v);
	list<StaticObject*> obj = gl_Quadtree->query_staticObj(_boundBox);
	for (StaticObject* i: obj)
	{
		if(i == _currentGround) continue;
		if(SweptAABB::checkAABB(_boundBox,i->getBox()))
			return true;
	}
	return false;
}

void MoveObject::fallDown()
{
	_fallFromGround = _currentGround;
	_mBox->_v.y = 0;
	_moveState = FALL_DOWN;
}

//xongok
bool MoveObject::checkOutGround()
{		
	if(_moveState == ON_SPACE || _moveState == CLIMB_LEFT || _moveState == CLIMB_RIGHT) return false;
	if (!SweptAABB::checkAABB(_getBoundBox(),_currentGround->getBox())) return false;	
	//ra ngoai han luon. hay ra mot nua thoi. mot nua rot là dep roi
	bool _chkLeft = _mBox->getLeft() + _mBox->_size.x/2 < _currentGround->getBox()->getLeft();
	bool _chkRight = _mBox->getRight() - _mBox->_size.x/2 > _currentGround->getBox()->getRight();
	return _chkLeft | _chkRight;
}

Box* MoveObject::_getMoveBox()
{
	if(_mBox->_v.x > 0)
	{
		if(_direction != 1) _direction = 1;
	}
	else if(_mBox->_v.x < 0)
	{
		if(_direction != -1) _direction = -1;
	}
	_moveBox->_position = _mBox->_position;
	_moveBox->_size = _mBox->_size;
	_moveBox->_v = _mBox->_v;
	if(_direction == 1)
	{
		_moveBox->_size.x /= 5;		
		_moveBox->_position.x += _moveBox->_size.x ;

	}else if(_direction == -1)
	{
		_moveBox->_size.x /= 5;
		_moveBox->_position.x = _mBox->getRight() - 2 * _moveBox->_size.x ;
	}
	return _moveBox;
}

Box* MoveObject::_getGround()
{
	if(_currentGround == NULL) return NULL;
	return _currentGround->getBox();
}

StaticObject* MoveObject::_getCurrentGround()
{
	return _moveState == ON_SPACE ? NULL : _currentGround;
}

bool MoveObject::moveDiagonalThrow()
{	
	if(_mBox->_position.y > 50)
	{
		_mBox->_position.x += _mBox->_v.x * cos(145 * M_PI / 180);	
		_mBox->_position.y += _mBox->_v.y * sin(145 * M_PI / 180);
		_mBox->_v.y+=g;
		return true;
	}	
	return false;		
}